// KeyAuth WebSocket SDK
class KeyAuthWS {
    constructor(url) {
        this.url = url;
        this.ws = null;
        this._pending = new Map();
        this._listeners = {};
        this.sessionToken = null;
        this.connectionInfo = null;
        this._loadConnectionInfoFromStorage();
    }
    connect(appInfo) {
        if (!appInfo) return Promise.reject(new Error('必须提供应用信息(appInfo)'));
        return new Promise((resolve, reject) => {
            const connectPromise = { resolve, reject };
            const connectInfo = { appInfo };
            this._listeners['open'] = (e) => {
                setTimeout(() => {
                    this._send('Connect', { app_info: connectInfo.appInfo, scopes: connectInfo.appInfo.scopes || ["sign", "verify", "did", "contract"] })
                        .then(r => {
                            if (r.status === 'success' && r.data) {
                                this.connectionInfo = r.data;
                                this.sessionToken = r.data.session_token;
                                this._saveConnectionInfoToStorage();
                            }
                            connectPromise.resolve(r);
                        })
                        .catch(connectPromise.reject);
                }, 500);
            };
            this._listeners['error'] = (e) => { connectPromise.reject(e); };
            this.ws = new WebSocket(this.url);
            this.ws.onopen = e => this._emit('open', e);
            this.ws.onclose = e => this._emit('close', e);
            this.ws.onerror = e => this._emit('error', e);
            this.ws.onmessage = e => {
                try {
                    const msg = JSON.parse(e.data);
                    if (msg.request_id && this._pending.has(msg.request_id)) {
                        this._pending.get(msg.request_id).resolve(msg);
                        this._pending.delete(msg.request_id);
                    }
                    this._emit('message', msg);
                } catch (err) { this._emit('error', err); }
            };
        });
    }
    disconnect() {
        this.connectionInfo = null;
        this.sessionToken = null;
        this._removeConnectionInfoFromStorage();
        if (this.ws) this.ws.close();
    }
    on(event, handler) { this._listeners[event] = handler; return this; }
    _emit(event, ...args) { if (typeof this._listeners[event] === 'function') this._listeners[event](...args); }
    _send(action, params = {}, request_id = null, client_info = null) {
        if (!this.ws || this.ws.readyState !== WebSocket.OPEN) throw new Error('WebSocket 未连接');
        const rid = request_id || this._generateUUID();
        const req = { action, params, request_id: rid, client_info };
        this.ws.send(JSON.stringify(req));
        return new Promise((resolve, reject) => {
            this._pending.set(rid, { resolve, reject });
            const timeoutId = setTimeout(() => {
                if (this._pending.has(rid)) {
                    this._pending.delete(rid);
                    reject(new Error(`请求超时: ${action}`));
                }
            }, 30000);
            const originalResolve = this._pending.get(rid).resolve;
            this._pending.set(rid, {
                resolve: result => { clearTimeout(timeoutId); originalResolve(result); },
                reject
            });
        });
    }
    _saveConnectionInfoToStorage() {
        try {
            if (typeof localStorage !== 'undefined' && this.connectionInfo) {
                localStorage.setItem('keyauth_connection_info', JSON.stringify({ connectionInfo: this.connectionInfo, sessionToken: this.sessionToken }));
            }
        } catch (e) {}
    }
    _loadConnectionInfoFromStorage() {
        try {
            if (typeof localStorage !== 'undefined') {
                const storedInfo = localStorage.getItem('keyauth_connection_info');
                if (storedInfo) {
                    const data = JSON.parse(storedInfo);
                    this.connectionInfo = data.connectionInfo;
                    this.sessionToken = data.sessionToken;
                    return true;
                }
            }
        } catch (e) {}
        return false;
    }
    _removeConnectionInfoFromStorage() {
        try { if (typeof localStorage !== 'undefined') localStorage.removeItem('keyauth_connection_info'); } catch (e) {}
    }
    ping() { return this._send('Ping', {}); }
    get connectionInfo() { return this._connectionInfo; }
    set connectionInfo(v) { this._connectionInfo = v; }
    get sessionToken() { return this._sessionToken; }
    set sessionToken(v) { this._sessionToken = v; }
    createSignedDID(didInfo) { return this._send('CreateSignedDID', { didInfo }); }
    verifyDID(didDocument) { return this._send('VerifyDID', { didDocument }); }
    invoke(chainID, nodeAddr, nodePort, contract, method, params) { return this._send('Invoke', { chainID, nodeAddr, nodePort, contract, method, params }); }
    query(chainID, nodeAddr, nodePort, contract, method, params) { return this._send('Query', { chainID, nodeAddr, nodePort, contract, method, params }); }
    signData(headerJson, payloadJson) { return this._send('SignData', { header: headerJson, payload: payloadJson }); }
    verifyData(headerJson, payloadJson, signature, publicKey) {
        if (!publicKey && this.connectionInfo && this.connectionInfo.authorized_keys && this.connectionInfo.authorized_keys.length > 0) {
            publicKey = this.connectionInfo.authorized_keys[0].public_key;
        }
        return this._send('VerifyData', { header: headerJson, payload: payloadJson, signature, publicKey });
    }
    _generateUUID() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
            const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }
}
window.KeyAuthWS = KeyAuthWS; 